package com.hzgj.soa.benchmark;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Properties;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;

public class BenchmarkClient extends AbstractBenchmarkClient {

    private static Logger logger = LoggerFactory.getLogger(BenchmarkClient.class);
    static Properties properties = new Properties();
    /**
     * 并发的Runable线程，是否使用相同的client进行调用。
     * true：并发线程只使用一个client（bean实例）调用服务。
     * false: 每个并发线程使用不同的Client调用服务
     */
    private static BenchmarkService benchmarkService;
    private static boolean isMultiClient;


    public static void main(String[] args) {
        loadProperties();
        int concurrent = Integer.parseInt(properties.getProperty("concurrent"));
        int runtime = Integer.parseInt(properties.getProperty("runtime"));
        String className = properties.getProperty("className");
        String params = properties.getProperty("params");
        isMultiClient = Boolean.parseBoolean(properties.getProperty("isMultiClient"));
        if (args.length == 5) {
            concurrent = Integer.parseInt(args[0]);
            runtime = Integer.parseInt(args[1]);
            className = args[2];
            params = args[3];
            isMultiClient = Boolean.parseBoolean(args[4]);
        }
        benchmarkService = getBenchmarkService();
        new BenchmarkClient().start(concurrent, runtime, className, params);
    }

    private static void loadProperties() {
        try {
            properties.load(ClassLoader.getSystemResourceAsStream("benchmark.properties"));
        } catch (IOException e) {
            logger.error("{}", e);
        }
    }

    @Override
    public ClientRunnable getClientRunnable(String className, String params, CyclicBarrier barrier,
                                            CountDownLatch latch, long startTime, long endTime) {
        BenchmarkService service;
        if (isMultiClient) {
            service = getBenchmarkService();
        } else {
            service = benchmarkService;
        }

        Class[] parameterTypes = new Class[]{BenchmarkService.class, String.class, CyclicBarrier.class,
                CountDownLatch.class, long.class, long.class};
        Object[] parameters = new Object[]{service, params, barrier, latch, startTime, endTime};

        ClientRunnable clientRunnable = null;
        try {
            clientRunnable = (ClientRunnable) Class.forName(className).getConstructor(parameterTypes).newInstance(parameters);
        } catch (InstantiationException | NoSuchMethodException | ClassNotFoundException | IllegalAccessException e) {
            logger.error("{}", e);
        } catch (InvocationTargetException e) {
            logger.error("{}", e);
        }

        return clientRunnable;
    }

    private static BenchmarkService getBenchmarkService() {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext(new String[]{"classpath*:consume.xml"});
        return applicationContext.getBean("benchmarkService", BenchmarkService.class);
    }
}
